module VGA_Controller(	
	//	Host Side
	iData,
	oAddress,						//Actual Pixel's memory address
	oAddressCropped,				//480x480
	oR_EN,							//Actual Pixel's validity
	oR_ENCropped,					//480x480
	//	VGA Side
	oVGA_R,
	oVGA_G,
	oVGA_B,
	oVGA_HS,
	oVGA_VS,
	oVGA_SYNC,
	oVGA_BLANK,
	oVGA_CLOCK,
	//	Control Signal
	iCLK,
	iRST_N,
	iEN
);						
				
//	Horizontal Parameter	( Pixel )
parameter	H_SYNC_CYC	=	96;
parameter	H_SYNC_BACK	=	45+3;
parameter	H_SYNC_ACT	=	640;	//	646
parameter	H_SYNC_ACT_CROPPED = 480;
parameter	H_SYNC_FRONT=	13+3;
parameter	H_SYNC_TOTAL=	800;
//	Virtical Parameter		( Line )
parameter	V_SYNC_CYC	=	2;
parameter	V_SYNC_BACK	=	30+2;
parameter	V_SYNC_ACT	=	480;	//	484
parameter	V_SYNC_FRONT=	9+2;
parameter	V_SYNC_TOTAL=	525;
//	Start Offset
parameter	X_START		=	H_SYNC_CYC+H_SYNC_BACK+4;
parameter	Y_START		=	V_SYNC_CYC+V_SYNC_BACK;

parameter H_BLANK	=	H_SYNC_FRONT+H_SYNC_CYC+H_SYNC_BACK;
parameter V_BLANK	=	V_SYNC_FRONT+V_SYNC_CYC+V_SYNC_BACK;



//	Host Side
reg [9:0] oX_Count;
reg [9:0] oY_Count;
reg [9:0] oX_CountCropped;
reg [9:0] oY_CountCropped;
output reg [18:0] oAddress;
output reg [18:0] oAddressCropped;
output reg oR_EN;
output reg oR_ENCropped;
input	[7:0]	iData;
//	VGA Side
output [9:0] oVGA_R;
output [9:0] oVGA_G;
output [9:0] oVGA_B;
output reg oVGA_HS;
output reg oVGA_VS;
output oVGA_SYNC;
output oVGA_BLANK;
output oVGA_CLOCK;
//	Control Signal
input	iCLK;
input	iRST_N;
input iEN;

//	Internal Registers and Wires
reg [9:0] H_Count;
reg [9:0] V_Count;

assign	oVGA_BLANK	=	oVGA_HS & oVGA_VS;
assign	oVGA_SYNC	=	1'b0;
assign	oVGA_CLOCK	=	iCLK;

reg [9:0] mVGA_R;
reg [9:0] mVGA_G;
reg [9:0] mVGA_B;

wire Color_EN;
assign Color_EN = oR_EN;

always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N) begin
		mVGA_G <= 0;
		mVGA_R <= 0;
		mVGA_B <= 0;
	end
	else begin
		if(Color_EN && iCLK && iEN) begin
			mVGA_R <= {iData[7:0],2'b00};
			mVGA_G <= {iData[7:0],2'b00};
			mVGA_B <= {iData[7:0],2'b00};
		end
		else begin
			mVGA_R <= 10'd0;
			mVGA_G <= 10'd0;
			mVGA_B <= 10'd0;
		end
	end
end


assign oVGA_R	=	(  H_Count>=X_START 	&& H_Count<X_START+H_SYNC_ACT &&
							V_Count>=Y_START 	&& V_Count<Y_START+V_SYNC_ACT)
							?	mVGA_R	:	10'd0;
assign oVGA_G	=	(	H_Count>=X_START 	&& H_Count<X_START+H_SYNC_ACT &&
							V_Count>=Y_START 	&& V_Count<Y_START+V_SYNC_ACT)
							?	mVGA_G :	10'd0;
assign oVGA_B	=	(	H_Count>=X_START 	&& H_Count<X_START+H_SYNC_ACT &&
							V_Count>=Y_START 	&& V_Count<Y_START+V_SYNC_ACT)
							?	mVGA_B	:	10'd0;

						
//	Pixel LUT Address Generator Cropped
always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N) begin
		oX_CountCropped	<=	10'd0;
		oY_CountCropped	<=	10'd0;
		oAddressCropped	<=	19'd0;
		oR_ENCropped <= 1'b0;
	end
	else begin
		if(	H_Count>=X_START && H_Count<X_START+H_SYNC_ACT_CROPPED &&
			V_Count>=Y_START && V_Count<Y_START+V_SYNC_ACT )
		begin
			oX_CountCropped	<=	H_Count-X_START;
			oY_CountCropped	<=	V_Count-Y_START;
			oAddressCropped <= oY_CountCropped*H_SYNC_ACT_CROPPED + oX_CountCropped;
			oR_ENCropped <= 1'b1;
		end
		else begin
			oR_ENCropped <= 1'b0;
		end
	end
end

//	Pixel LUT Address Generator
always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N) begin
		oX_Count	<=	10'd0;
		oY_Count	<=	10'd0;
		oAddress	<=	19'd0;
		oR_EN <= 1'b0;
	end
	else begin
		if(	H_Count>=X_START && H_Count<X_START+H_SYNC_ACT &&
			V_Count>=Y_START && V_Count<Y_START+V_SYNC_ACT )
		begin
			oX_Count	<=	H_Count-X_START;
			oY_Count	<=	V_Count-Y_START;
			oAddress <= oY_Count*H_SYNC_ACT + oX_Count;
			oR_EN <= 1'b1;
		end
		else begin
			oR_EN <= 1'b0;
		end
	end
end
 
//	H_Sync Generator, Ref. 25.175 MHz Clock
always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N)
	begin
		H_Count	<=	10'd0;
		oVGA_HS	<=	1'b0;
	end
	else begin
		//	H_Sync Counter
		if( H_Count < H_SYNC_TOTAL )
			H_Count	<=	H_Count+1'b1;
		else
			H_Count	<=	10'd0;
		//	H_Sync Generator
		if( H_Count < H_SYNC_CYC )
			oVGA_HS	<=	1'b0;
		else
			oVGA_HS	<=	1'b1;	
	end
end

 
//	V_Sync Generator, Ref. H_Sync
always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N)
	begin
		V_Count <= 10'd0;
		oVGA_VS	<=	1'b0;
	end
	else begin
		//	When H_Sync Re-start
		if(H_Count==10'd0) begin
			//	V_Sync Counter
			if( V_Count < V_SYNC_TOTAL )
				V_Count	<=	V_Count + 1'b1;
			else
				V_Count	<=	10'd0;
			//	V_Sync Generator
			if(	V_Count < V_SYNC_CYC )
				oVGA_VS	<=	1'b0;
			else
				oVGA_VS	<=	1'b1;
		end
	end
end

endmodule
